/*
 * Copyright (C) 2003, Velocityme Partnership
 * RoleSessionBean.java
 *
 * Created on 21 April 2003, 06:21
 */

package com.velocityme.session;

import com.velocityme.entity.ChangeDeltaItemTypeBean;
import com.velocityme.entity.ChangeDeltaTypeBean;
import com.velocityme.entity.PermissionBean;
import javax.ejb.*;
import javax.naming.*;
import java.util.*;
import com.velocityme.interfaces.*;
import com.velocityme.utility.InvalidKeyException;
import com.velocityme.utility.PermissionCache;
import com.velocityme.utility.PermissionDeniedException;
import com.velocityme.valueobjects.*;
import java.rmi.RemoteException;

/**
 *
 * @author  Robert Crida Work
 * @ejb.bean
 *           type="Stateless"
 *           cmp-version="2.x"
 *           name="RoleSession"
 *           jndi-name="ejb/RoleSession"
 *           view-type="local"
 *           transaction-type="Container"
 * @ejb.transaction type="Required"
 *
 * @ejb.util generate="physical"
 */
public class RoleSessionBean implements SessionBean {
    
    private SessionContext m_context;

    private SearchSessionLocal m_searchSessionLocal;

    private PermissionLocal m_permissionRoleCreate;
    private PermissionLocal m_permissionRoleEdit;
    private PermissionLocal m_permissionNodeView;

    /**
     * If the user has permission to create a new Role in the specified parent
     * node then go ahead and create it and log an appropriate ChangeDelta.
     *
     * @param p_key User's security key
     * @param p_parentNode The node which will contain the new Role
     * @param p_roleValue The value details for the Role part of the role
     * @param p_permissions The set of permissions assigned to the role (Strings)
     *
     * @ejb.interface-method view-type="local"
     **/
    public RoleLocal createRole(KeySessionLocal p_keyLocal,
                                NodeLocal p_parentNodeLocal,
                                com.velocityme.valueobjects.RoleValue p_roleValue,
                                java.util.Set p_permissionLocals)
        throws PermissionDeniedException, InvalidKeyException {
        try {
            if (m_searchSessionLocal.getAssignedPermissionsLocal(p_keyLocal, p_parentNodeLocal).contains(m_permissionRoleCreate)) {
                p_roleValue.getNodeValue().setType("Role");
                p_roleValue.getNodeValue().setFinalType("Role");
                DBObjectLocal dBObjectLocal = DBObjectUtil.getLocalHome().create();
                NodeValue nodeValue = p_roleValue.getNodeValue();
                NodeLocal nodeLocal = NodeUtil.getLocalHome().create(dBObjectLocal, nodeValue, p_parentNodeLocal);
                nodeValue.setNodeId(nodeLocal.getNodeId());
                RoleLocal roleLocal = RoleUtil.getLocalHome().create(nodeLocal, p_roleValue, p_permissionLocals);
                ChangeDeltaLocal changeDeltaLocal = ChangeDeltaUtil.getLocalHome().create(new Date(), ChangeDeltaTypeBean.CREATE, p_keyLocal.getUserLocal(), dBObjectLocal);
                changeDeltaLocal.addItem(ChangeDeltaItemTypeBean.NAME, nodeValue.getName());
                changeDeltaLocal.addItem(ChangeDeltaItemTypeBean.DESCRIPTION, nodeValue.getDescription());
                changeDeltaLocal.addItem(ChangeDeltaItemTypeBean.RECURSIVE, p_roleValue.getIsRecursive().toString());
                Iterator i = p_permissionLocals.iterator();
                while(i.hasNext()) {
                    changeDeltaLocal.addItem(ChangeDeltaItemTypeBean.ADD_PERMISSION, ((PermissionLocal)i.next()).getName());
                }
                changeDeltaLocal.addItem(ChangeDeltaItemTypeBean.PARENT_NODE, p_parentNodeLocal.getPathName());
                return roleLocal;
            }
            else
                throw new PermissionDeniedException();
        }
        catch(NamingException e) {
            throw new EJBException(e);
        }
        catch(CreateException e) {
            throw new EJBException(e);
        }
    }
    
    /**
     * If the user has permission to edit the Role then do so and log the
     * changes with an appropriate ChangeDelta.
     *
     * @param p_key User's security key
     * @param p_role The Role object being editted
     * @param p_roleValue The value details for the Role part of the role
     *
     * @ejb.interface-method view-type="local"
     **/
    public void editRole(KeySessionLocal p_keyLocal,
                         RoleLocal p_roleLocal,
                         com.velocityme.valueobjects.RoleValue p_roleValue,
                         java.util.Set p_permissionLocals)
        throws PermissionDeniedException, InvalidKeyException {
        try {
            NodeLocal nodeLocal = p_roleLocal.getNodeLocal();
            if (m_searchSessionLocal.getAssignedPermissionsLocal(p_keyLocal, nodeLocal).contains(m_permissionRoleEdit)) {
                NodeValue nodeValue = p_roleValue.getNodeValue();
                ChangeDeltaLocal changeDeltaLocal = ChangeDeltaUtil.getLocalHome().create(new Date(), ChangeDeltaTypeBean.EDIT, p_keyLocal.getUserLocal(), nodeLocal.getDBObjectLocal());
                if (!nodeValue.getName().equals(nodeLocal.getName()))
                    changeDeltaLocal.addItem(ChangeDeltaItemTypeBean.NAME, nodeValue.getName());
                if (!nodeValue.getDescription().equals(nodeLocal.getDescription()))
                    changeDeltaLocal.addItem(ChangeDeltaItemTypeBean.DESCRIPTION, nodeValue.getDescription());
                if (!p_roleValue.getIsRecursive().equals(p_roleLocal.getIsRecursive()))
                    changeDeltaLocal.addItem(ChangeDeltaItemTypeBean.RECURSIVE, p_roleValue.getIsRecursive().toString());
                Set permissionsBefore = p_roleLocal.getPermissionsLocal();
                Set permissionsDisabled = new HashSet(permissionsBefore);
                permissionsDisabled.removeAll(p_permissionLocals);
                Set permissionsEnabled = new HashSet(p_permissionLocals);
                permissionsEnabled.removeAll(permissionsBefore);
                Iterator i = permissionsDisabled.iterator();
                while(i.hasNext()) {
                    changeDeltaLocal.addItem(ChangeDeltaItemTypeBean.REMOVE_PERMISSION, ((PermissionLocal)i.next()).getName());
                }
                i = permissionsEnabled.iterator();
                while(i.hasNext()) {
                    changeDeltaLocal.addItem(ChangeDeltaItemTypeBean.ADD_PERMISSION, ((PermissionLocal)i.next()).getName());
                }
                nodeLocal.setNodeValue(nodeValue);
                p_roleLocal.setRoleValue(p_roleValue);
                p_roleLocal.setPermissionsLocal(p_permissionLocals);
                // clear the permission cache
                PermissionCache.getInstance().clear();
            }
            else
                throw new PermissionDeniedException();
        }
        catch(NamingException e) {
            throw new EJBException(e);
        }
        catch(CreateException e) {
            throw new EJBException(e);
        }
    }
    
    /**
     * If the user has permission to access a role then return the local object.
     *
     * @param p_key User's security key
     * @param p_rolePK The Role object to lookup
     *
     * @ejb.interface-method view-type="local"
     **/
    public RoleLocal getRoleLocal(KeySessionLocal p_keyLocal, 
                                  RolePK p_rolePK)
        throws PermissionDeniedException, InvalidKeyException {
        try {
            RoleLocal roleLocal = RoleUtil.getLocalHome().findByPrimaryKey(p_rolePK);
            NodeLocal nodeLocal = roleLocal.getNodeLocal();
            if (m_searchSessionLocal.getAssignedPermissionsLocal(p_keyLocal, nodeLocal).contains(m_permissionNodeView)) {
                return roleLocal;
            }
            else
                throw new PermissionDeniedException();
        }
        catch(NamingException e) {
            throw new EJBException(e);
        }
        catch(FinderException e) {
            throw new EJBException(e);
        }
    }
    
    /**
     * Get the full list of user value objects.
     *
     * @param p_key User's security key
     *
     * @ejb.interface-method view-type="local"
     **/
    public com.velocityme.valueobjects.RoleValue[] getAllValueObjects(KeySessionLocal p_keyLocal) throws InvalidKeyException {
        RoleValue[] values = null;
        try {
            if (p_keyLocal.isValid()) {
                Collection roles = RoleUtil.getLocalHome().findAll();
                values = new RoleValue[roles.size()];
                int j = 0;
                Iterator i = roles.iterator();
                while(i.hasNext()) {
                    RoleLocal roleLocal = (RoleLocal)i.next();
                    values[j++] = new RoleValueToString(roleLocal.getRoleValue());
                }
            }
            else
                throw new InvalidKeyException();
        }
        catch(NamingException e) {
            throw new EJBException(e);
        }
        catch(FinderException e) {
            throw new EJBException(e);
        }
        return values;
    }
    
    /**
     * Get the set of assigned permission values for a role.
     *
     * @param p_key User's security key
     * @param p_roleLocal The role
     *
     * @ejb.interface-method view-type="local"
     **/
    public java.util.Set getAssignedPermissionValues(KeySessionLocal p_keyLocal,
                                                     RoleLocal p_roleLocal) throws InvalidKeyException {
        Set permissionValues = new java.util.TreeSet();
        if (p_keyLocal.isValid()) {
            Iterator i = p_roleLocal.getPermissionsLocal().iterator();
            while (i.hasNext()) {
                permissionValues.add(new PermissionValueToString(((PermissionLocal)i.next()).getPermissionValue()));
            }
        }
        else
            throw new InvalidKeyException();
        return permissionValues;
    }
    
    /**
     * Create the Session Bean.
     * @throws CreateException 
     * @ejb:create-method view-type="remote"
     */
    public void ejbCreate() throws CreateException {
        try {
            m_searchSessionLocal = SearchSessionUtil.getLocalHome().create();
            m_permissionRoleCreate = PermissionUtil.getLocalHome().findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.ROLE_CREATE)));
            m_permissionRoleEdit = PermissionUtil.getLocalHome().findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.ROLE_EDIT)));
            m_permissionNodeView = PermissionUtil.getLocalHome().findByPrimaryKey(new PermissionPK(new Integer(PermissionBean.NODE_VIEW)));
        }
        catch(NamingException e) {
            throw new CreateException(e.getMessage());
        }
        catch(FinderException e) {
            throw new CreateException(e.getMessage());
        }
    }

    public void ejbActivate() throws java.rmi.RemoteException {
    }
    
    public void ejbPassivate() throws java.rmi.RemoteException {
    }
    
    public void ejbRemove() throws java.rmi.RemoteException {
    }
    
    public void setSessionContext(javax.ejb.SessionContext sessionContext) throws java.rmi.RemoteException {
        m_context = sessionContext;
    }
    
}
